'''
Created on Nov 11, 2011

@author: victor
'''

import copy
import io
import utils

######################################################################
class Unit:

    def __init__(self, name, utypename, colour, bgcolour, x, y):
        self.name = name
        self.utypename = utypename
        self.colour = colour
        self.bgcolour = bgcolour
        self.x = x
        self.y = y
        self.reset_move_dest()
        self.attrs = {}
        self.xbm = None

    def __cmp__(self, other):
        return cmp(self.name, other.name)

    def full_cmp(self, other):
        as0 = self.get_all_attrs()
        as1 = other.get_all_attrs()
        anames = as0.keys() + as1.keys()
        anames.sort()
        for a in anames:
            result = cmp(as0.get(a,None), as1.get(a,None))
            if result != 0:
                return result
        return 0

    def attr_cmp(self, other, exclude=None):
        as0 = self.get_all_attrs(exclude)
        as1 = other.get_all_attrs(exclude)
        result = {}
        anames = as0.keys()
        anames.sort()
        for a in anames:
            v0, v1 = (as0.get(a, None), as1.get(a,None))
            if v0 != v1:
                result[a] = (v0, v1)
        anames = [ n for n in as1.keys() if n not in as0 ]
        anames.sort()
        for a in anames:
            v0, v1 = (as0.get(a, None), as1.get(a,None))
            if v0 != v1:
                result[a] = (v0, v1)
        return result

    def __hash__(self):
        return hash(self.name) ^ 7243 # 7243 is prime

    def __copy__(self):        
        u = Unit(self.name,
                 self.utypename,
                 self.colour,
                 self.bgcolour,
                 self.x,
                 self.y)
        u.move_dest = copy.copy(self.move_dest)
        u.attrs = utils.copydict(self.attrs)
        return u

    @classmethod
    def required_attrs(cls):
        return ["name", "location", "unittype", "color", "bgcolor"]

    def update(self, other):
        self.attrs = copy.copy(other.attrs)

    def update_attrs(self, attrs):
        # 'name' cannot be updated with this method
        if 'color' in attrs:
            if self.colour != attrs['color']:
                self.colour = attrs['color']

        if 'bgcolor' in attrs:
            if self.bgcolour != attrs['bgcolor']:
                self.bgcolour = attrs['bgcolor']
            
        if 'location' in attrs:
            x, y = eval(attrs['location'])
            if (x,y) != (self.x, self.y):
                self.x, self.y = x, y
                self.reset_move_dest()

        for a in Unit.required_attrs():
            if a in attrs:
                del attrs[a]
        self.attrs.update(attrs)

    def last_move_xy(self):
        return self.move_dest[-1]

    def set_last_move_xy(self, x, y):
        self.move_dest[-1] = (x,y)
        if len(self.move_dest) == 1:
            self.x = x
            self.y = y
            
    def last_move_x(self):
        return self.last_move_xy()[0]

    def last_move_y(self):
        return self.last_move_xy()[1]

    def add_move_dest(self, x, y):
        self.move_dest.append((x,y))

    def nr_move_dests(self):
        # do not count the current (first) position
        return len(self.move_dest) - 1 
    
    def reset_move_dest(self):
        self.move_dest = [(self.x, self.y)]        

    def get_move_dests(self):
        return self.move_dest[1:]

    def set_move_dests(self, moves):
        self.move_dest[1:] = moves
        
    def set_xy(self, x, y):
        self.x = x
        self.y = y
        self.move_dest[0] = (x, y)
        
    def delete_last_move_dest(self, nr):
        # pre: self.nr_move_dests() > 0
        del self.move_dest[-1]
        
    def execute_move(self):
        if self.nr_move_dests()>0:
            self.x, self.y = self.last_move_xy()
            self.reset_move_dest()
        self.check_loc_move()
        assert len(self.move_dest) == 1
        
    def check_loc_move(self):
        x,y = self.move_dest[0]
        assert ((self.x == x) and (self.y == y))

    def get_all_attrs(self, exclude=None):
        all_attrs = copy.copy(self.attrs)
        all_attrs["location"] = "(%d,%d)" % (self.x, self.y)
        all_attrs["unittype"] = "%s" % self.utypename
        all_attrs["color"] = "%s" % self.colour
        all_attrs["bgcolor"] = "%s" % self.bgcolour
        if self.nr_move_dests()>0:
            all_attrs["move"] = "%s" % " -> ".join(
                ["(%d,%d)" % (x, y) for x,y in self.move_dest])
        if exclude is not None:
            for k in exclude:
                if k in all_attrs:
                    del all_attrs[k]
        return all_attrs

    def get_save_str(self):
        result = []
        result.append("begin Unit %s\n" % self.name)
        result.append(io.attrs_to_str(self.get_all_attrs(), spc="  "))
        result.append("\nend Unit %s\n" % self.name)
        return "".join(result)

    def get_attr_str(self, spc=""):
        return io.attrs_to_str(self.attrs, spc=spc)

